/**
 * 
 */
package rebol.eclipse.plugin.helpers;

import java.beans.XMLDecoder;
import java.beans.XMLEncoder;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.sql.Time;
import java.util.Date;

import rebol.eclipse.plugin.xml.rebol.Path;
import rebol.eclipse.plugin.xml.rebol.RTime;
import rebol.eclipse.plugin.xml.rebol.Tuple;

/**
 * @author volker
 * 
 */
public class Rebol {

	/**
	 * @param path
	 * @param args
	 * @param data
	 * @param debug
	 * @return
	 */
	public static String call(File path, String args, String data, boolean debug) {
		String cmd = Config.rebolCallBase() + ' ' + path.getAbsolutePath()
				+ ' ' + args;
		System.out.println(cmd);

		try {
			Process p = Runtime.getRuntime().exec(cmd);
			OutputStream os = p.getOutputStream();
			for (int i = 0; i < data.length(); i++) {
				if (debug) {
					//System.out.print(data.charAt(i));
				}
				os.write(data.charAt(i));
			}
			os.close();

			if (debug) {
				System.out.println("==");
			}

			InputStream is = p.getInputStream();
			StringBuffer sb = new StringBuffer();
			int c;
			while (-1 != (c = is.read())) {
				sb.append((char) c);
				if (debug) {
					System.out.print((char) c);
				}
			}
			if (debug) {
				System.out.println(";;");
			}
			return sb.toString();
		} catch (IOException e) {
			e.printStackTrace();
		}

		return null;

	}

	public static void testCall() {
		// RunRebol.printProperties();
		printConfig();
		File path = new File(Config.scriptDir, "test-call.r");
		String res = Rebol.call(path, "arg", "data\n", true);
		System.out.println("---");
		System.out.println(res);
	}

	public static void printConfig() {
		String pathS = System.getProperty("user.dir");
		System.out.println("Current dir: " + pathS + "\n" + "Scripts: "
				+ Config.scriptDir.getAbsolutePath() + "\nExes: "
				+ Config.exes.getAbsolutePath());
	}

	public static Object call(File path, String args, Object[] data,
			boolean debug) {

		ByteArrayOutputStream bos = new ByteArrayOutputStream();
		XMLEncoder xe = new XMLEncoder(bos);
		xe.writeObject(data);
		xe.close();

		String inp = bos.toString();
		String res = Rebol.call(path, args, inp, false);
		return loadBeans(res,debug);
	}

	private static Object loadBeans(String res, boolean debug) {
		String mark = "-bean-result-\n";
		int resIx = res.indexOf(mark);
		if (-1 != resIx){
			String resData = res.substring(resIx + mark.length() );
			if (debug) {
				Log.s("Debug: " + res.substring(0,resIx + mark.length()));
				Log.s("Data: " + resData);
			}
			XMLDecoder xd = new XMLDecoder(new ByteArrayInputStream(resData.getBytes()));
			Object o = xd.readObject();
			xd.close();
			return o;
		}
		if (debug) {
			Log.s(res);
			Log.s("No bean-result");
		}
		return null;
	}

	public static void testXMLCall() {
		printConfig();
		Log.s("calling");
		Object res = call(new File(Config.scriptDir, "test-xml-call.r"), "test",
				new Object[] { 
			//
//			"tricky-chars", new RString("<>&`^, rest normal"), 1, 2.2, new Point(11,12),
//			new Object[] {1,2,3},
//			new Word("word"),
//			new GetWord("word"),
//			new SetWord("word"),
//			new LitWord("word"),
//			new Point(1,2),
//			'j', 
//			true, 
//			false,
//			new Paren(new Object[]{"a" , "test"}),
			new Path(new Object[]{"a" , "test"}),
			new Date(),
			new RTime(new Time(5000)),
			new Tuple(new byte[]{1,2,3}),
				}, true);
		Log.s("called");
		ByteArrayOutputStream bos = new ByteArrayOutputStream();
		XMLEncoder xe = new XMLEncoder(bos);
		xe.writeObject(res);
		xe.close();
		Log.s(bos.toString());
	}

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		// testCall();
		testXMLCall();
	}

}
